package com.admin_system.config;

import com.admin_system.entity.TemplateConfig;

import java.io.*;
import java.nio.file.*;
import java.util.*;

/**
 * 模板配置提供类
 * 负责管理Excel模板配置和Python脚本执行环境
 * 根据不同人数提供相应的模板配置，并处理资源文件的提取和临时存储
 */
public class TemplateConfigProvider {
    /**
     * 存储所有模板配置的静态映射
     * 键为人数上限，值为对应的模板配置对象
     */
    private static final Map<Integer, TemplateConfig> TEMPLATE_CONFIG;
    
    /**
     * Python可执行文件的资源路径
     * 用于Excel到PDF的转换处理
     */
    private static final String PYTHON_EXE_RESOURCE_PATH = "python-exe/excel_to_pdf.exe";
    
    /**
     * 提取后的Python可执行文件路径
     * 存储在临时目录中，用于实际调用
     */
    private final Path extractedPythonExePath;

    /**
     * 静态初始化块
     * 创建并配置所有支持的模板配置
     * 根据人数范围（40-100人）设置不同的模板文件和参数
     */
    static {
        TemplateConfigBuilder builder = new TemplateConfigBuilder();
        String basePath = "templates/";
        // 为不同人数范围添加模板配置
        builder.addConfig(40, basePath + "模板表-40.xlsx", 3, 21);
        builder.addConfig(50, basePath + "模板表-50.xlsx", 3, 26);
        builder.addConfig(60, basePath + "模板表-60.xlsx", 3, 31);
        builder.addConfig(70, basePath + "模板表-70.xlsx", 3, 36);
        builder.addConfig(80, basePath + "模板表-80.xlsx", 3, 41);
        builder.addConfig(90, basePath + "模板表-90.xlsx", 3, 46);
        builder.addConfig(100, basePath + "模板表-100.xlsx", 3, 51);
        TEMPLATE_CONFIG = builder.build();
    }

    /**
     * 构造函数
     * 初始化时提取Python可执行文件到临时目录
     * 
     * @throws RuntimeException 如果Python可执行文件提取失败
     */
    public TemplateConfigProvider() {
        try {
            // 将内嵌的Python可执行文件提取到临时目录
            extractedPythonExePath = extractResourceToTemp(PYTHON_EXE_RESOURCE_PATH);
        } catch (IOException e) {
            throw new RuntimeException("无法提取Python可执行文件", e);
        }
    }

    /**
     * 获取所有模板配置
     * 
     * @return 包含所有模板配置的不可变映射
     */
    public Map<Integer, TemplateConfig> getTemplateConfigMap() {
        return TEMPLATE_CONFIG;
    }

    /**
     * 根据人数上限获取对应的模板配置
     * 
     * @param maxSize 人数上限（40, 50, 60, 70, 80, 90或100）
     * @return 对应的模板配置对象，如果不存在则返回null
     */
    public TemplateConfig getTemplateConfig(int maxSize) {
        return TEMPLATE_CONFIG.get(maxSize);
    }

    /**
     * 获取Python可执行文件的路径
     * 
     * @return Python可执行文件在临时目录中的路径
     */
    public Path getPythonExePath() {
        return extractedPythonExePath;
    }

    /**
     * 从资源文件中提取文件到临时目录
     * 用于将内嵌的资源文件（如可执行文件）提取出来以供运行时使用
     * 
     * @param resourcePath 资源文件路径
     * @return 提取后文件在临时目录中的路径
     * @throws IOException 如果提取过程中发生I/O错误
     * @throws FileNotFoundException 如果指定的资源文件不存在
     */
    private Path extractResourceToTemp(String resourcePath) throws IOException {
        // 从类加载器中获取资源文件输入流
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(resourcePath);
        if (inputStream == null) {
            throw new FileNotFoundException("资源未找到: " + resourcePath);
        }
        
        // 创建临时目录
        Path tempDir = Files.createTempDirectory("python-exe");
        // 在临时目录中创建目标文件
        Path tempFile = tempDir.resolve(Paths.get(resourcePath).getFileName());
        
        // 将资源文件内容写入临时文件
        try (OutputStream outputStream = Files.newOutputStream(tempFile)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
        
        // 设置可执行权限（对于Windows不是必需的，但对于Unix/Linux是必需的）
        tempFile.toFile().setExecutable(true);
        return tempFile;
    }

    /**
     * 模板配置建造者类
     * 使用建造者模式创建模板配置映射
     * 提供链式API以简化配置过程
     */
    private static class TemplateConfigBuilder {
        /**
         * 存储配置信息的映射
         * 键为人数上限，值为对应的模板配置
         */
        private final Map<Integer, TemplateConfig> configMap = new HashMap<>();

        /**
         * 链式添加模板配置
         * 为指定人数上限创建并添加模板配置
         *
         * @param maxSize     人数上限
         * @param filePath    模板文件路径
         * @param dataStart   数据开始行（1-based）
         * @param lastDataRow 最后数据行（1-based）
         * @return 建造者实例，用于链式调用
         */
        public TemplateConfigBuilder addConfig(int maxSize, String filePath, int dataStart, int lastDataRow) {
            configMap.put(maxSize, new TemplateConfig(filePath, dataStart, lastDataRow));
            return this;
        }

        /**
         * 构建模板配置映射
         * 将构建好的配置映射转换为不可变映射
         *
         * @return 不可变的模板配置映射
         */
        public Map<Integer, TemplateConfig> build() {
            return Collections.unmodifiableMap(configMap);
        }
    }
}